package com.example.webdriveddd.controller;

import com.example.webdriveddd.application.AppException;
import com.example.webdriveddd.application.Application;
import com.example.webdriveddd.application.NotFoundException;
import com.example.webdriveddd.domain.FileInfo;
import com.example.webdriveddd.domain.User;
import com.example.webdriveddd.dto.*;
import com.example.webdriveddd.repository.FileRepository;
import com.example.webdriveddd.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.util.Set;

@RestController
public class FileController {
    @Autowired
    private Application application;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private FileRepository fileRepository;

    String currentUserName() {
        return SecurityContextHolder.getContext().getAuthentication().getName();
    }

    @GetMapping("/files")
    public FolderDTO listFiles(@RequestParam("fileId") int fileId) throws AppException {
        return application.getFolder(currentUserName(), fileId);
    }

    @GetMapping("/files/search")
    public Set<FileInfoDTO> search(@RequestParam("keyword") String keyword) throws AppException{
        return application.search(currentUserName(),keyword);
    }

    @PostMapping("/files/new")
    public FileInfoDTO newFile(@RequestBody FileInfoDTO fileInfoDTO) throws AppException {
        User user=userRepository.findByUsername(currentUserName()).orElseThrow(()->{
            return new NotFoundException("user with name "+currentUserName()+" not found",null);
        });
        fileInfoDTO.setUserId(user.getId());
        return application.newFile(fileInfoDTO);
    }

    @GetMapping("/files/delete")
    public void delete(@RequestParam("fileId")int fileId){
        application.delete(fileId);
    }

    @GetMapping("/files/move")
    public void move(@RequestParam("sourceId")int sourceId, @RequestParam("targetDirId")int targetDirId) throws AppException {
        application.move(sourceId, targetDirId);
    }

    @GetMapping("/files/tag")
    public void putTagToFile(@RequestParam("fileId")int fileId,@RequestParam("tag")String tag) throws AppException {
        application.putTagToFile(fileId, tag);
    }

    @GetMapping("/files/tag/delete")
    public void deleteTag(@RequestParam("fileId")int fileId,@RequestParam("tag")String tag) throws AppException {
        application.removeTagFromFile(fileId,tag);
    }

    @GetMapping("/tags")
    public Set<FileTagDTO> tags() throws AppException {
        return application.findTagsByUsername(currentUserName());
    }

    @GetMapping("/tags/files")
    public Set<FileInfoDTO> findFilesByTag(@RequestParam("tag")String tag) throws AppException {
        return application.findFilesByTag(currentUserName(),tag);
    }

    @GetMapping("/files/tags")
    public Set<FileTagDTO> findTagsByFile(@RequestParam("fileId")int fileId) throws AppException {
        return application.getFileTags(fileId);
    }

    @GetMapping("/files/share")
    public FileInfoDTO shareFile(@RequestParam("fileId")int fileId,@RequestParam("password")String password) throws AppException {
        return application.shareFile(fileId, password);
    }

    @GetMapping("/files/save")
    public FileInfoDTO saveFile(@RequestParam("fileId")int fileId,@RequestParam("password")String password,@RequestParam("targetDirId")int targetDirId) throws AppException {
        return application.saveShare(currentUserName(),password,fileId,targetDirId);
    }

    @GetMapping("/share")
    public ShareInfoDTO sharedFile(@RequestParam("fileId")int fileId) throws AppException {
        return application.accessFile(fileId);
    }

    @GetMapping("/files/share/cancel")
    public FileInfoDTO cancelShare(@RequestParam("fileId")int fileId) throws AppException {
        return application.cancelShare(fileId);
    }

    @GetMapping("/files/path")
    public FolderDTO listByPath(@RequestParam("path")String path) throws AppException {
        return application.getFolderByPath(currentUserName(),path);
    }

    @GetMapping("/share/save")
    public FileInfoDTO saveFile(@RequestParam("fileId")int fileId) throws AppException {
        FileInfo fileInfo=fileRepository.findById(fileId).orElseThrow(()->new NotFoundException("file with id "+fileId+" not found",null));
        if(!fileInfo.isShare()){
            throw new AppException("file with id "+fileId+" is not share",null);
        }
        return application.saveShare(currentUserName(),fileId);
    }

    @GetMapping("/share/verify")
    public VerifyResult verify(@RequestParam("fileId")int fileId,@RequestParam("password")String password) throws AppException {
        FileInfo fileInfo=fileRepository.findById(fileId).orElseThrow(()->new NotFoundException("file with id "+fileId+" not found",null));
        if (!fileInfo.isShare()){
            throw new AppException("file is not share",null);
        }
        VerifyResult verifyResult=new VerifyResult();
        if (!fileInfo.verifySharePassword(password)){
            verifyResult.setMsg("密码错误");
            verifyResult.setSuccess(false);
        }else{
            verifyResult.setSuccess(true);
        }
        return verifyResult;
    }
}
